#pragma once

#if defined __APPLE__ && defined __MACH__
#include <GLUT/glut.h>
#include <OpenGL/OpenGL.h>
#elif defined _WIN32 || defined _WIN64
#include <GL\glut.h>
#endif

#include "vec3f.h"
#include <iostream>
#include <cmath>

class Camera
{
public:

	static const float PI;

	Camera(void);
	~Camera(void);

	void update() const;
	void pitch(const GLfloat);
	void pitchUp(const GLfloat);
	void pitchDown(const GLfloat);
	void yaw(const GLfloat);
	void yawLeft(const GLfloat);
	void yawRight(const GLfloat);
	void roll(const GLfloat);
	void rollLeft(const GLfloat);
	void rollRight(const GLfloat);
	void moveTo(const GLfloat, const GLfloat, const GLfloat);
	void lookAt(const GLfloat, const GLfloat, const GLfloat);
	void lookAt(const GLfloat, const GLfloat, const GLfloat, const GLfloat, const GLfloat, const GLfloat);
	void moveForward(const GLfloat);
	void moveBackward(const GLfloat);
	void moveLeft(const GLfloat);
	void moveRight(const GLfloat);
	void moveUp(const GLfloat);
	void moveDown(const GLfloat);
	void slide(const GLfloat, const GLfloat, const GLfloat);

private:

	GLfloat * cm; // camera matrix

	Vec3f * xaxis;
	Vec3f * yaxis;
	Vec3f * zaxis;

	Vec3f * eyeP;
	Vec3f * centerP;

	void rotatePointAboutAnArbitraryAxis(const GLfloat, const Vec3f &, const Vec3f &, Vec3f &) const;
	void matrix4by4TimesMatrix4by4(const GLfloat *, const GLfloat *, GLfloat *) const;
	void matrix4by4TimesVector(const GLfloat *, const Vec3f &, Vec3f &) const;
	void translatef(const GLfloat, const GLfloat, const GLfloat, GLfloat *) const;
	void loadIdentity(GLfloat *) const;
	void setAxisFromEyeAndCenterPoint();
	void setAxisFromCameraMatrix();
	void setEyeAndCenterPointFromCameraMatrix();
	void setCameraMatrix();
};